package com.koron.order.repair.service.impl;

import cn.hutool.json.JSONUtil;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.koron.bean.query.PageQuery;
import com.koron.bean.system.staff.po.AppUserPo;
import com.koron.common.core.util.CodeTools;
import com.koron.common.core.util.message.MessageUtil;
import com.koron.order.common.bean.base.OrderType;
import com.koron.order.common.bean.po.*;
import com.koron.order.common.service.*;
import com.koron.order.common.tools.CommonCodeTools;
import com.koron.order.common.tools.OrderCodeEnum;
import com.koron.order.experiment.feign.PlanIssueFeignService;
import com.koron.order.maintain.bean.entity.MaintainStatus;
import com.koron.order.repair.bean.convertor.RepairConvertor;
import com.koron.order.repair.bean.dto.RepairDetailDto;
import com.koron.order.repair.bean.entity.RepairEquipmentPo;
import com.koron.order.repair.bean.entity.RepairPo;
import com.koron.order.repair.bean.entity.RepairReadyPo;
import com.koron.order.repair.bean.entity.RepairStatus;
import com.koron.order.repair.bean.query.RepairQuery;
import com.koron.order.repair.bean.vo.RepairDetailVo;
import com.koron.order.repair.bean.vo.RepairVo;
import com.koron.order.repair.mapper.RepairMapper;
import com.koron.order.repair.service.RepairEquipmentService;
import com.koron.order.repair.service.RepairExecuteService;
import com.koron.order.repair.service.RepairReadyService;
import com.koron.order.repair.service.RepairService;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.koron.ebs.mybatis.SessionFactory;
import org.koron.ebs.mybatis.TaskAnnotation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * (Repair)表服务实现类
 *
 * @author zhouj
 * @since 2021-09-13 17:42:14
 */
@Service("repairService")
public class RepairServiceImpl implements RepairService {

    @Autowired
    private RepairReadyService repairReadyService;

    @Autowired
    private RepairEquipmentService repairEquipmentService;

    @Autowired
    private OrderInstructionService orderInstructionService;

    @Autowired
    private RepairConvertor repairConvertor;

    @Autowired
    private RepairExecuteService executeService;

    @Autowired
    private OrderExecuteService orderExecuteService;

    //工单的设备列表
    @Autowired
    private OrderEquipService orderEquipService;

    //作业单位
    @Autowired
    private OrderWorkDeptService workDeptService;

    @Autowired
    private PlanIssueFeignService planIssueFeignService;

    /*工单的工作地点*/
    @Autowired
    OrderLocationService orderLocationService;

    @Autowired
    MessageUtil messageUtil;

    @Override
    @TaskAnnotation("insert")
    public int insert(SessionFactory factory, RepairPo repair) {

        RepairMapper mapper = factory.getMapper(RepairMapper.class);
        return mapper.insert(repair);
    }

    @Override
    @TaskAnnotation("update")
    public int update(SessionFactory factory, RepairPo repair) {
        RepairMapper mapper = factory.getMapper(RepairMapper.class);
        return mapper.update(repair);
    }

    @Override
    @TaskAnnotation("updateStatus")
    public boolean updateStatus(SessionFactory factory, String id, String status) {
        RepairMapper mapper = factory.getMapper(RepairMapper.class);
        RepairPo repairPo = new RepairPo();
        repairPo.setId(id);
        repairPo.setStatus(status);
        return mapper.update(repairPo) > 0;
    }

    @Override
    @TaskAnnotation("deleteById")
    public int deleteById(SessionFactory factory, String id) {
        RepairMapper mapper = factory.getMapper(RepairMapper.class);
        return mapper.deleteById(id);
    }

    @Override
    @TaskAnnotation("queryById")
    public RepairDetailVo queryById(SessionFactory factory, String id) {
        //维护id 查询详情
        RepairMapper mapper = factory.getMapper(RepairMapper.class);
        //1.1 计划检修工单主表信息
        RepairPo repairPo = mapper.queryById(id);

        RepairDetailVo repairDetailVo = repairConvertor.beanToRepairDetailVo(repairPo);

        //1.2 计划检修工单 作业准备
        List<RepairReadyPo> repairReadyPoList = repairReadyService.queryByOrderId(factory, id);

        RepairEquipmentPo repairEquipmentPo = new RepairEquipmentPo();
        repairEquipmentPo.setRepairId(id);
        //1.2 计划检修工单 检修设备
        List<RepairEquipmentPo> repairEquipmentPos = repairEquipmentService.queryList(factory, repairEquipmentPo);

        //1.3 计划检修工单 作业指导书
        List<OrderInstructionBean> orderInstructionBeans = orderInstructionService.queryByBizId(factory, id);
        //1.4 计划检修工单 工单设备
        List<OrderEquipPo> orderEquipPos = orderEquipService.queryByOrderId(factory, id);
        //1.5 工作地点列表
        List<OrderLocationPo> orderLocationPos = orderLocationService.queryByOrderId(factory, id);

        repairDetailVo.setRepairReadyPoList(repairReadyPoList);
        repairDetailVo.setRepairEquipmentPoList(repairEquipmentPos);
        repairDetailVo.setOrderInstructionBeanList(orderInstructionBeans);
        repairDetailVo.setOrderEquipPoList(orderEquipPos);
        repairDetailVo.setOrderLocationList(orderLocationPos);

        return repairDetailVo;
    }

    @Override
    @TaskAnnotation("queryRepairBeanById")
    public RepairPo queryRepairBeanById(SessionFactory factory, String id) {
        //维护id 查询详情
        RepairMapper mapper = factory.getMapper(RepairMapper.class);
        RepairPo repairPo = mapper.queryById(id);

        return repairPo;
    }

    @Override
    @TaskAnnotation("queryList")
    public PageInfo queryList(SessionFactory factory, RepairQuery query, PageQuery pageQuery) {

        PageHelper.startPage(pageQuery.getPage(), pageQuery.getPageSize(), pageQuery.getOrderBy());
        RepairMapper mapper = factory.getMapper(RepairMapper.class);

        List<RepairVo> vos = mapper.queryList(query);

        if (CollectionUtils.isNotEmpty(vos)) {

            vos.forEach(p -> {
                String trafficLight = CommonCodeTools.calcTrafficLight(p.getFactEndTime(), p.getStartTime(), p.getEndTime(), p.getStatus());
                p.setTrafficLight(trafficLight);
            });


            //----------------以下采用批量工单ids查询提升效率

            List<String> orderIds = vos.stream().map(RepairVo::getId).collect(Collectors.toList());
            //1.1 查询工单的作业单位
            List<OrderWorkDeptPo> orderWorkDeptPos = workDeptService.queryByOrderIds(factory, orderIds);
            //设置进列表
            if (CollectionUtils.isNotEmpty(orderWorkDeptPos)) {
                Map<String, List<OrderWorkDeptPo>> cond = orderWorkDeptPos.stream().collect(Collectors.groupingBy(OrderWorkDeptPo::getOrderId));
                for (RepairVo repairVo : vos) {
                    repairVo.setWorkDeptPoList(cond.getOrDefault(repairVo.getId(), new ArrayList<>()));
                }
            }

            //1.2 查询工单的设备列表
            List<OrderEquipPo> orderEquipPos = orderEquipService.queryByOrderIds(factory, orderIds);
            //设置进列表
            if (CollectionUtils.isNotEmpty(orderEquipPos)) {
                Map<String, List<OrderEquipPo>> cond = orderEquipPos.stream().collect(Collectors.groupingBy(OrderEquipPo::getOrderId));
                for (RepairVo repairVo : vos) {
                    repairVo.setOrderEquipPoList(cond.getOrDefault(repairVo.getId(), new ArrayList<>()));
                }
            }

            // 如果选了需要作业表单则查询出作业表单中的设备信息
            vos.stream().filter(repairVo -> repairVo.getNeedStatus().equals(1)).forEach(
                    repairVo -> {
                        RepairEquipmentPo repairEquipmentPo = new RepairEquipmentPo();
                        repairEquipmentPo.setRepairId(repairVo.getId());
                        //1.2 计划检修工单 检修设备
                        List<RepairEquipmentPo> repairEquipmentPos = repairEquipmentService.queryList(factory, repairEquipmentPo);
                        repairVo.setRepairEquipmentPos(repairEquipmentPos);
                    }
            );

        }

        return new PageInfo(vos);
    }

    @Override
    @TaskAnnotation("submitRepair")
    public int submitRepair(SessionFactory factory, String repairId, String status, OrderDispatch orderDispatch) {

        RepairMapper mapper = factory.getMapper(RepairMapper.class);
        //对于工单id 及状态做处理
        RepairPo repairPo = queryRepairBeanById(factory, repairId);
        Assert.notNull(repairPo, "工单id无效");
        String preStatus = repairPo.getStatus();

        //将要改变的状态
        RepairStatus repairStatus = RepairStatus.getRepairStatus(status);
        Assert.notNull(repairStatus, "状态修改,枚举不能为空");

        if (StringUtils.isNotEmpty(preStatus)) {
            RepairStatus preRepairStatus = RepairStatus.getRepairStatus(preStatus);
            Assert.notNull(preRepairStatus, "数据有误");
            Assert.isTrue(repairStatus.getSort() - preRepairStatus.getSort() == 1, "不可重复提交");
        } else {
            Assert.isTrue(StringUtils.equalsAny(repairStatus.getStatus(),
                    RepairStatus.DRAFT.getStatus(), RepairStatus.WAIT_DISPATCH.getStatus()), "修改工单状态失败");
        }
        RepairPo po = new RepairPo();
        po.setId(repairId);
        po.setCode(repairPo.getCode());
        po.setStatus(status);
        //状态变为待验收时-->设置为实际完成时间

        //计划产生的则需要通知计划那边
        if (StringUtils.equalsAnyIgnoreCase("plan_order",repairPo.getSourceId())) {
            switch (status) {
                case "IN_EXECUTE":
                    planIssueFeignService.issueExecute(po.getCode());
                    break;
                case "ARCHIVED":
                    planIssueFeignService.issueFinish(po.getCode());
                    break;
                default:
                    break;
            }
        }

        if (StringUtils.equals(status, RepairStatus.WAIT_ACCEPT.getStatus())) {
            Date factEndTime = orderExecuteService.queryMaxFactEndTimeByOrderId(factory, repairId);
            po.setFactEndTime(factEndTime);
        }

        int result = mapper.update(po);
        // 检修工单发送派工通知
        if (StringUtils.equals(status, MaintainStatus.WAIT_EXECUTE.getStatus())) {
            if (com.koron.common.core.util.StringUtils.isNotEmpty(orderDispatch.getTopicWorker())) {
                String topicWorkerJson = orderDispatch.getTopicWorker();
                List<AppUserPo> userPoList = JSONUtil.parseArray(topicWorkerJson).toList(AppUserPo.class);
                String handler = userPoList.stream().map(AppUserPo::getAccount).collect(Collectors.joining(","));
                sendMessage(handler, orderDispatch, repairPo);
            }
        }
        return result;

    }

    private void sendMessage(String handler, OrderDispatch orderDispatch, RepairPo repairPo) {
        String qywxHref = messageUtil.generateQywxHref("transmit_" + orderDispatch.getOrderType() + "_order", orderDispatch.getOrderId(),"","");
        messageUtil.sendMessageWithTemplate("dispatch_notice", qywxHref, handler, repairPo.getContext());
    }

    @Override
    @TaskAnnotation("insertOrUpdate")
    public String insertOrUpdate(SessionFactory factory, RepairDetailDto dto) {

        //1.1 基础信息
        RepairPo repairPo = repairConvertor.dtoToBean(dto);

        repairPo.setStatus(dto.getIsCommit() ? RepairStatus.WAIT_DISPATCH.getStatus() : RepairStatus.DRAFT.getStatus());

        String repairId;

        if (StringUtils.isEmpty(repairPo.getId())) {
            repairId = CodeTools.getCode32();
            repairPo.setId(repairId);
            repairPo.setCode(CommonCodeTools.getNormalOrderCode(OrderCodeEnum.JX));
            insert(factory, repairPo);
        } else {
            repairId = repairPo.getId();
            update(factory, repairPo);
        }

        //1.2 作业准备
        List<RepairReadyPo> repairReadyPoList = dto.getRepairReadyPoList();

        if (!CollectionUtils.isEmpty(repairReadyPoList)) {
            repairReadyPoList.forEach(p -> {
                p.setRepairId(repairId);
            });
            repairReadyService.insertBatch(factory, repairReadyPoList);
        } else {
            repairReadyService.deleteByOrderId(factory, repairId);
        }

        //1.3 作业过程
        List<RepairEquipmentPo> repairEquipmentPoList = dto.getRepairEquipmentPoList();
        if (!CollectionUtils.isEmpty(repairEquipmentPoList)) {
            repairEquipmentPoList.forEach(p -> {
                p.setRepairId(repairId);
            });
            repairEquipmentService.insertBatch(factory, repairEquipmentPoList);
        } else {
            repairEquipmentService.deleteByOrderId(factory, repairId);
        }
        //1.4 作业指导书
        List<OrderInstructionBean> orderInstructionBeanList = dto.getOrderInstructionBeanList();
        if (!CollectionUtils.isEmpty(orderInstructionBeanList)) {
            orderInstructionBeanList.forEach(p -> {
                p.setBussinessId(repairId);
                p.setOrderType(OrderType.REPAIR);
            });
            orderInstructionService.insertBatch(factory, orderInstructionBeanList);
        } else {
            orderInstructionService.deleteByBizId(factory, repairId, OrderType.REPAIR);
        }

        //1.5 工单中的设备
        List<OrderEquipPo> orderEquipPoList = dto.getOrderEquipPoList();
        if (!CollectionUtils.isEmpty(orderEquipPoList)) {
            orderEquipPoList.forEach(p -> {
                p.setOrderId(repairId);
                p.setOrderType(OrderType.REPAIR);
            });
            orderEquipService.insertBatch(factory, orderEquipPoList);
        } else {
            orderEquipService.deleteByOrderId(factory,repairId);
        }

        //1.6 工作地点
        List<OrderLocationPo> orderLocationList = dto.getOrderLocationList();

        String location = repairPo.getLocation();
        String locationName = repairPo.getLocationName();

        if (!StringUtils.isAllEmpty(location,locationName)) {
            OrderLocationPo orderLocationPo = new OrderLocationPo();
            orderLocationPo.setLocation(location);
            orderLocationPo.setLocationName(locationName);
            orderLocationList.add(orderLocationPo);
        }
        if (CollectionUtils.isNotEmpty(orderLocationList)) {
            orderLocationList.forEach(p -> {
                p.setOrderId(repairId);
                p.setOrderType(OrderType.REPAIR);
            });
            orderLocationService.insertBatch(factory, orderLocationList);
        } else {
            orderLocationService.deleteByOrderId(factory, repairId);
        }

        //1.7 生成项目及记录项记录
        executeService.generateStand(factory, repairId);

        return repairId;
    }

}